package com.tulei.shuqi;

import com.tulei.common.utils.file.ExcelHandler;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.annotations.XYTextAnnotation;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PiePlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.labels.StandardPieSectionLabelGenerator;
import org.jfree.chart.renderer.category.LineAndShapeRenderer;
import org.jfree.chart.renderer.xy.XYBubbleRenderer;
import org.jfree.chart.ui.ApplicationFrame;
import org.jfree.chart.ui.UIUtils;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.data.general.DefaultPieDataset;
import org.jfree.data.xy.DefaultXYZDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;

import javax.swing.JPanel;
import java.awt.Font;
import java.awt.GridLayout;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.Comparator;

public class ShuQi {

    public static void main(String[] args) throws InterruptedException {
        List<Book> list = new ExcelHandler().readExcel("books.xlsx", Book.class);
        createCombinedChart(list);
    }

    private static void createCombinedChart(List<Book> books) {
        ApplicationFrame frame = new ApplicationFrame("Book Charts");

        // 创建四个图表的面板
        ChartPanel pieChartPanel = new ChartPanel(createPieChart(books));
        ChartPanel barChartPanel = new ChartPanel(createBarChart(books));
        ChartPanel lineChartPanel = new ChartPanel(createLineChart(books));
        ChartPanel scatterPlotPanel = new ChartPanel(createScatterPlot(books));

        // 使用 GridLayout 布局将四个图表面板放在同一个窗口中
        JPanel panel = new JPanel(new GridLayout(2, 2));
        panel.add(pieChartPanel);
        panel.add(barChartPanel);
        panel.add(lineChartPanel);
        panel.add(scatterPlotPanel);

        frame.setContentPane(panel);
        frame.pack();
        UIUtils.centerFrameOnScreen(frame);
        frame.setVisible(true);
    }

    private static JFreeChart createPieChart(List<Book> books) {
        Map<String, Integer> categoryCount = new HashMap<>();
        for (Book book : books) {
            String category = book.getCategory();
            categoryCount.put(category, categoryCount.getOrDefault(category, 0) + 1);
        }

        DefaultPieDataset dataset = new DefaultPieDataset();
        for (Map.Entry<String, Integer> entry : categoryCount.entrySet()) {
            dataset.setValue(entry.getKey(), entry.getValue());
        }

        JFreeChart pieChart = ChartFactory.createPieChart(
                "Book Category Distribution",
                dataset,
                true, true, false);

        PiePlot plot = (PiePlot) pieChart.getPlot();
        plot.setLabelGenerator(new StandardPieSectionLabelGenerator("{0}: {1}"));

        // 使用系统字体以支持中文字符
        Font font = Font.decode("SansSerif-PLAIN-12");
        plot.setLabelFont(font);
        pieChart.getTitle().setFont(font);
        pieChart.getLegend().setItemFont(font);

        return pieChart;
    }

    private static JFreeChart createBarChart(List<Book> books) {
        Map<String, Integer> categoryCount = new HashMap<>();
        for (Book book : books) {
            String category = book.getCategory();
            categoryCount.put(category, categoryCount.getOrDefault(category, 0) + 1);
        }

        List<Map.Entry<String, Integer>> sortedCategories = categoryCount.entrySet()
                .stream()
                .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
                .limit(5)
                .collect(Collectors.toList());

        DefaultCategoryDataset dataset = new DefaultCategoryDataset();
        for (int i = 0; i < sortedCategories.size(); i++) {
            Map.Entry<String, Integer> entry = sortedCategories.get(i);
            dataset.addValue(entry.getValue(), "Number of Books", entry.getKey());
        }

        JFreeChart barChart = ChartFactory.createBarChart(
                "Top 5 Book Categories",
                "Category",
                "Number of Books",
                dataset,
                PlotOrientation.VERTICAL,
                true, true, false);

        CategoryPlot plot = (CategoryPlot) barChart.getPlot();
        // 设置中文字体
        Font chineseFont = new Font("宋体", Font.PLAIN, 12);
        plot.getDomainAxis().setLabelFont(chineseFont);
        plot.getDomainAxis().setTickLabelFont(chineseFont);
        plot.getRangeAxis().setLabelFont(chineseFont);
        barChart.getTitle().setFont(chineseFont);
        barChart.getLegend().setItemFont(chineseFont);

        return barChart;
    }

    private static JFreeChart createLineChart(List<Book> books) {
        Map<Integer, Integer> titleLengthCount = new HashMap<>();
        for (Book book : books) {
            int titleLength = book.getTitle().length();
            titleLengthCount.put(titleLength, titleLengthCount.getOrDefault(titleLength, 0) + 1);
        }

        DefaultCategoryDataset dataset = new DefaultCategoryDataset();
        for (Map.Entry<Integer, Integer> entry : titleLengthCount.entrySet()) {
            dataset.addValue(entry.getValue(), "Number of Books", entry.getKey());
        }

        JFreeChart lineChart = ChartFactory.createLineChart(
                "Book Title Length Distribution",
                "Title Length",
                "Number of Books",
                dataset,
                PlotOrientation.VERTICAL,
                true, true, false);

        CategoryPlot plot = (CategoryPlot) lineChart.getPlot();
        Font font = Font.decode("SansSerif-PLAIN-12");
        plot.getDomainAxis().setLabelFont(font);
        plot.getRangeAxis().setLabelFont(font);
        lineChart.getTitle().setFont(font);
        lineChart.getLegend().setItemFont(font);

        // 设置折线图的渲染器
        LineAndShapeRenderer renderer = new LineAndShapeRenderer();
        plot.setRenderer(renderer);

        return lineChart;
    }

    private static JFreeChart createScatterPlot(List<Book> books) {
        XYSeriesCollection dataset = new XYSeriesCollection();

        // 创建一个自定义比较器来处理字数
        Comparator<Book> wordCountComparator = (b1, b2) -> {
            String wordCountStr1 = b1.getWordCount().replace("万字", "").replaceAll("[^\\d.]", "");
            String wordCountStr2 = b2.getWordCount().replace("万字", "").replaceAll("[^\\d.]", "");
            double count1 = wordCountStr1.isEmpty() ? 0 : Double.parseDouble(wordCountStr1);
            double count2 = wordCountStr2.isEmpty() ? 0 : Double.parseDouble(wordCountStr2);
            if (b1.getWordCount().contains("万字")) count1 *= 10000;
            if (b2.getWordCount().contains("万字")) count2 *= 10000;
            return Double.compare(count2, count1); // 降序排序
        };

        // 根据字数对书籍排序
        List<Book> sortedBooks = books.stream()
                .sorted(wordCountComparator)
                .limit(10)
                .collect(Collectors.toList());

        // 创建一个系列来存储书籍数据
        XYSeries series = new XYSeries("Top 10 Books by Word Count");

        // 添加书籍数据到系列中
        for (int i = 0; i < sortedBooks.size(); i++) {
            Book book = sortedBooks.get(i);
            String wordCountStr = book.getWordCount().replace("万字", "").replaceAll("[^\\d.]", "");
            double wordCount = wordCountStr.isEmpty() ? 0 : Double.parseDouble(wordCountStr);
            if (book.getWordCount().contains("万字")) wordCount *= 10000;
            series.add(i, (int) Math.round(wordCount)); // 用书籍字数作为X轴，用索引作为Y轴，并四舍五入到最接近的整数
        }

        // 添加系列到数据集
        dataset.addSeries(series);

        StringBuilder titles = new StringBuilder();
        for (int i = 0; i < sortedBooks.size(); i++) {
            titles.append(i).append(":").append(sortedBooks.get(i).getTitle()).append("  ");
        }
        // 创建散点图
        JFreeChart scatterPlot = ChartFactory.createScatterPlot(
                "Top 10 Books by Word Count",
                titles.toString(),
                "Word Count",
                dataset,
                PlotOrientation.VERTICAL,
                true, true, false);

        // 设置字体
        Font font = Font.decode("SansSerif-PLAIN-12");
        Font font1 = Font.decode("SansSerif-PLAIN-16");
        XYPlot plot = (XYPlot) scatterPlot.getPlot();
        plot.getDomainAxis().setLabelFont(font1);
        plot.getRangeAxis().setLabelFont(font);
        scatterPlot.getTitle().setFont(font);
        scatterPlot.getLegend().setItemFont(font);
        return scatterPlot;
    }

    public static JFreeChart createBubbleChart(List<Book> books) {
        DefaultXYZDataset dataset = new DefaultXYZDataset();

        books.stream().map(Book::getAuthor).distinct().forEach(author -> {
            List<Book> authorBooks = books.stream()
                    .filter(book -> book.getAuthor().equals(author))
                    .collect(Collectors.toList());

            double[][] data = new double[3][authorBooks.size()];

            for (int i = 0; i < authorBooks.size(); i++) {
                Book book = authorBooks.get(i);
                double categoryLength = book.getTitle().length(); // 使用类别长度
                double authorNameLength = book.getAuthor().length();
                double descriptionSize = book.getDescription().length() / 200;
                data[0][i] = categoryLength; // 修改这里
                data[1][i] = authorNameLength;
                data[2][i] = descriptionSize;
            }
            dataset.addSeries(author, data);
        });

        JFreeChart bubbleChart = ChartFactory.createBubbleChart(
                "Author and Book Characteristics",
                "Category Length", // 修改这里
                "Author Name Length",
                dataset,
                PlotOrientation.VERTICAL,
                true, true, false);

        XYPlot plot = (XYPlot) bubbleChart.getPlot();
        XYBubbleRenderer renderer = new XYBubbleRenderer();
        plot.setRenderer(renderer);

        Font font = Font.decode("SansSerif-PLAIN-12");
        plot.getDomainAxis().setLabelFont(font);
        plot.getRangeAxis().setLabelFont(font);
        bubbleChart.getTitle().setFont(font);
        bubbleChart.getLegend().setItemFont(font);

        return bubbleChart;
    }
}
